/***************************************************************************
  qgsrubberband3d.h
  --------------------------------------
  Date                 : June 2021
  Copyright            : (C) 2021 by Martin Dobias
  Email                : wonder dot sk at gmail dot com
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef QGSRUBBERBAND3D_H
#define QGSRUBBERBAND3D_H

#include "qgis_3d.h"

#define SIP_NO_FILE

/// @cond PRIVATE

//
//  W A R N I N G
//  -------------
//
// This file is not part of the QGIS API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
//

#include "qgslinestring.h"

class QgsWindow3DEngine;
class QgsLineMaterial;
class Qgs3DMapSettings;
class QgsBillboardGeometry;
class QgsMarkerSymbol;
class QgsPoint3DBillboardMaterial;

namespace Qt3DCore
{
  class QEntity;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
  class QBuffer;
  class QGeometry;
  class QAttribute;
#endif
}

namespace Qt3DRender
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
  class QBuffer;
  class QGeometry;
  class QAttribute;
#endif
  class QGeometryRenderer;
  class QMaterial;
}

/**
 * \ingroup 3d
 * Rubber band implementation for use in 3D map views.
 *
 * Coordinates are expected to be passed in map CRS and the 3D entity generated by this
 * class will be attached to the parentEntity given in the constructor (normally this
 * should be the root entity, i.e. map scene object).
 *
 * \note Currently only supports linestring geometry.
 * \since QGIS 3.20
 */
class _3D_EXPORT QgsRubberBand3D
{
  public:
    QgsRubberBand3D( Qgs3DMapSettings &map, QgsWindow3DEngine *engine, Qt3DCore::QEntity *parentEntity );
    ~QgsRubberBand3D();

    float width() const;
    void setWidth( float width );

    QColor color() const;
    void setColor( QColor color );

    void reset();

    void addPoint( const QgsPoint &pt );

    void removeLastPoint();

    void moveLastPoint( const QgsPoint &pt );

    //! Sets whether the marker on the last vertex is displayed. We typically do not want it displayed while it is still tracked by the mouse.
    void setShowLastMarker( bool show ) { mShowLastMarker = show; }

  private:
    void updateGeometry();
    void updateMarkerMaterial();

  private:
    QgsLineString mLineString;
    bool mShowLastMarker = false;

    Qgs3DMapSettings *mMapSettings = nullptr;  // not owned
    QgsWindow3DEngine *mEngine = nullptr;

    Qt3DCore::QEntity *mLineEntity = nullptr;  // owned by parentEntity (from constructor)
    Qt3DCore::QEntity *mMarkerEntity = nullptr; // owned by parentEntity (from constructor)

    // all these are owned by mLineEntity
    Qt3DRender::QGeometryRenderer *mGeomRenderer = nullptr;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    Qt3DRender::QGeometry *mGeometry = nullptr;
    Qt3DRender::QAttribute *mPositionAttribute = nullptr;
    Qt3DRender::QAttribute *mIndexAttribute = nullptr;
#else
    Qt3DCore::QGeometry *mGeometry = nullptr;
    Qt3DCore::QAttribute *mPositionAttribute = nullptr;
    Qt3DCore::QAttribute *mIndexAttribute = nullptr;
#endif
    QgsLineMaterial *mLineMaterial = nullptr;

    // and these are owned by mMarkerEntity
    Qt3DRender::QGeometryRenderer *mMarkerGeometryRenderer = nullptr;
    QgsBillboardGeometry *mMarkerGeometry = nullptr;
    QgsPoint3DBillboardMaterial *mMarkerMaterial = nullptr;
    QgsMarkerSymbol *mMarkerSymbol = nullptr;

    // Disable copying as we have pointer members.
    QgsRubberBand3D( const QgsRubberBand3D & ) = delete;
    QgsRubberBand3D &operator= ( const QgsRubberBand3D & ) = delete;
};

/// @endcond

#endif // QGSRUBBERBAND3D_H
